// 这段代码展示了类型擦除的一种典型设计模式：通过基类指针管理派生类对象，以统一接口处理不同类型
#pragma once

#include <memory>

class Any { // 形成“接口指针 + 具体实现类”这种经典的类型擦除模式
public:
  Any() = default;
  ~Any() = default;
  Any(const Any &) = delete;
  Any &operator=(const Any &) = delete;
  Any(Any &&) = default;
  Any &operator=(Any &&) = default;
  
  template <typename T>
  Any(T data): base_(std::make_unique<Derive<T>>(data)) {} // 指向动态分配的 Derive<T> 对象，实现类型擦除
public:
  template <typename T>
  T cast_() {
    Derive<T>* p = dynamic_cast<Derive<T>*>(base_.get());
    if (p == nullptr) {
      throw std::invalid_argument("type unmatch!\n");
    }

    return p->data_;
  }
private:
  class Base { // 作为多态层次的顶层，持有虚析构函数，保证通过 Base* 删除派生类对象时能正确调用析构函数
  public:
    virtual ~Base() = default;
  };

  template <typename T>
  class Derive : public Base { // 持有具体存储类型 T 的数据成员 data_; 每种 T 都会生成一个新的派生类类型
  public:
    Derive(T data) : data_{data} {};
    T data_;
  };

private:
  std::unique_ptr<Base> base_;
};